package com.pay.paytoken.activity.lock;

import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.widget.TextView;

import com.pay.paytoken.R;
import com.pay.paytoken.base.BaseActivity;
import com.pay.paytoken.patternLock.ViewAccessibilityCompat;

import java.util.ArrayList;
import java.util.List;

import appUtils.LogUtil;
import appUtils.ToastUtil;
import butterknife.Bind;
import butterknife.OnClick;
import weightUtils.PatternUtils;
import weightUtils.PatternView;

import static com.pay.paytoken.activity.lock.LockManager.TYPE;

/**
 * 设置手势密码与修改手势密码
 */
public class GestureSetLockActivity extends BaseActivity implements PatternView.OnPatternListener {
    private static final String KEY_STAGE = "stage";
    private static final String KEY_PATTERN = "pattern";
    private static final int CLEAR_PATTERN_DELAY_MILLI = 2000;
    private static final int CONFIRM = 0x1;
    @Bind(R.id.tv_pattern_title)
    TextView mTvPatternTitle;
    @Bind(R.id.pl_pattern)
    PatternView mPlPattern;
    @Bind(R.id.layout_title_textName)
    TextView mTitleTv;
    private final Runnable mClearPatternRunnable = new Runnable() {
        public void run() {
            // clearPattern() resets display mode to DisplayMode.Correct.
            if (null != mPlPattern) {
                mPlPattern.clearPattern();
            }
        }
    };
    private int mMinPatternSize;
    private List<PatternView.Cell> mPattern;
    private Stage mStage;
    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case CONFIRM:
                    onRightButtonClicked();
                    break;
            }
        }
    };
    //0为设置手势密码 1为修改手势密码
    public int mType;

    @Override
    public int setView() {
        return R.layout.activity_set_pattern;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


    }

    protected void onSetPattern(List<PatternView.Cell> pattern) {
        if (mType == 0) {
            ToastUtil.showShort(R.string.set_success);
        } else {
            ToastUtil.showShort(R.string.modify_success);
        }
        String patternSha1 = PatternUtils.patternToSha1String(pattern);
        LockManager.getInstance().saveGesturePass(TextUtils.isDigitsOnly(patternSha1) ? "" : patternSha1);
        LogUtil.log("gesrture pass = " + patternSha1);
    }

    @Override
    public void initData(Bundle savedInstanceState) {
        Intent intent = getIntent();
        if (intent != null) {
            mType = intent.getIntExtra(TYPE, 0);
        }
        mMinPatternSize = getMinPatternSize();
        if (savedInstanceState == null) {
            updateStage(Stage.Draw);
        } else {
            String patternString = savedInstanceState.getString(KEY_PATTERN);
            if (patternString != null) {
                mPattern = PatternUtils.stringToPattern(patternString);
            }
            updateStage(Stage.values()[savedInstanceState.getInt(KEY_STAGE)]);
        }
        if(mType == 1){
            mTvPatternTitle.setText(getString(R.string.please_draw_new_lock_pattern));
        }else if(mType ==0){
            mTvPatternTitle.setText(getString(R.string.please_draw_the_unlock_pattern));
        }
    }

    @Override
    public void initView() {
        mPlPattern.setOnPatternListener(this);
        mTitleTv.setText(R.string.please_draw_the_unlock_pattern);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putInt(KEY_STAGE, mStage.ordinal());
        if (mPattern != null) {
            outState.putString(KEY_PATTERN, PatternUtils.patternToString(mPattern));
        }
    }

    @Override
    public void onPatternStart() {
        removeClearPatternRunnable();
        mTvPatternTitle.setText(R.string.pl_recording_pattern);
        mPlPattern.setDisplayMode(PatternView.DisplayMode.Correct);
    }

    @Override
    public void onPatternCellAdded(List<PatternView.Cell> pattern) {
    }

    @Override
    public void onPatternDetected(List<PatternView.Cell> newPattern) {
        switch (mStage) {
            case Draw:
            case DrawTooShort:
                if (newPattern.size() < mMinPatternSize) {
                    updateStage(Stage.DrawTooShort);
                } else {
                    mPattern = new ArrayList<>(newPattern);
                    updateStage(Stage.DrawValid);
                }
                break;
            case Confirm:
            case ConfirmWrong:
                if (newPattern.equals(mPattern)) {
                    if (mType == 1) {
                        updateStage(Stage.ConfirmUpdate);
                    } else {
                        updateStage(Stage.ConfirmCorrect);
                    }
                } else {
                    updateStage(Stage.ConfirmWrong);
                }
                break;
            default:
                throw new IllegalStateException("Unexpected stage " + mStage + " when "
                        + "entering the pattern.");
        }
    }

    @Override
    public void onPatternCleared() {
        removeClearPatternRunnable();
    }

    @OnClick(R.id.layout_title_ivSecond)
    void onLeftButtonClicked() {
        if (mStage.leftButtonState == LeftButtonState.Redraw) {
            mPattern = null;
            updateStage(Stage.Draw);
        } else if (mStage.leftButtonState == LeftButtonState.Cancel) {
            mPattern = null;
            updateStage(Stage.Draw);
        } else {
            throw new IllegalStateException("left footer button pressed, but stage of " + mStage
                    + " doesn't make sense");
        }
    }

    private void onRightButtonClicked() {
        if (mStage.rightButtonState == RightButtonState.Continue) {
            if (mStage != Stage.DrawValid) {
                throw new IllegalStateException("expected ui stage " + Stage.DrawValid
                        + " when button is " + RightButtonState.Continue);
            }
            updateStage(Stage.Confirm);
        } else if (mStage.rightButtonState == RightButtonState.Confirm) {
            if (mStage != Stage.ConfirmCorrect && mStage != Stage.ConfirmUpdate) {
                throw new IllegalStateException("expected ui stage " + Stage.ConfirmCorrect
                        + " when button is " + RightButtonState.Confirm);
            }
            onSetPattern(mPattern);
            onConfirmed();
        }
    }

    protected void onConfirmed() {
        setResult(RESULT_OK);
        finish();
    }

    private void updateStage(Stage newStage) {

        Stage previousStage = mStage;
        mStage = newStage;

        if (mStage == Stage.DrawTooShort) {
            mTvPatternTitle.setText(getString(mStage.messageId, mMinPatternSize));
        } else {
            mTvPatternTitle.setText(mStage.messageId);
        }

        if (mStage.rightButtonState.enabled) {
            mHandler.sendEmptyMessageDelayed(CONFIRM, 500);
        }

        mPlPattern.setInputEnabled(mStage.patternEnabled);

        switch (mStage) {
            case Draw:
                // clearPattern() resets display mode to DisplayMode.Correct.
                mPlPattern.clearPattern();
                break;
            case DrawTooShort:
                mPlPattern.setDisplayMode(PatternView.DisplayMode.Wrong);
                postClearPatternRunnable();
                break;
            case DrawValid:
                break;
            case Confirm:
                mPlPattern.clearPattern();
                break;
            case ConfirmWrong:
                mPlPattern.setDisplayMode(PatternView.DisplayMode.Wrong);
                postClearPatternRunnable();
                break;
            case ConfirmCorrect:
                break;
        }

        // If the stage changed, announce the header for accessibility. This
        // is a no-op when accessibility is disabled.
        if (previousStage != mStage) {
            ViewAccessibilityCompat.announceForAccessibility(mTvPatternTitle, mTvPatternTitle.getText());
        }
    }

    protected int getMinPatternSize() {
        return 3;
    }

    protected void removeClearPatternRunnable() {
        mPlPattern.removeCallbacks(mClearPatternRunnable);
    }

    protected void postClearPatternRunnable() {
        removeClearPatternRunnable();
        mPlPattern.postDelayed(mClearPatternRunnable, CLEAR_PATTERN_DELAY_MILLI);
    }

    @OnClick(R.id.layout_title_iv_left)
    protected void back() {
        finish();
    }

    private enum LeftButtonState {
        Cancel(R.string.pl_cancel, true),
        CancelDisabled(R.string.pl_cancel, false),
        Redraw(R.string.pl_redraw, true),
        RedrawDisabled(R.string.pl_redraw, false);

        public final int textId;

        public final boolean enabled;

        LeftButtonState(int textId, boolean enabled) {
            this.textId = textId;
            this.enabled = enabled;
        }

    }

    private enum RightButtonState {

        Continue(R.string.pl_continue, true),
        ContinueDisabled(R.string.pl_continue, false),
        Confirm(R.string.pl_confirm, true),
        ConfirmDisabled(R.string.pl_confirm, false);

        public final int textId;

        public final boolean enabled;

        RightButtonState(int textId, boolean enabled) {
            this.textId = textId;
            this.enabled = enabled;
        }

    }

    private enum Stage {

        Draw(R.string.pl_draw_pattern, LeftButtonState.Cancel, RightButtonState.ContinueDisabled,
                true),
        DrawTooShort(R.string.pl_pattern_too_short, LeftButtonState.Redraw,
                RightButtonState.ContinueDisabled, true),
        DrawValid(R.string.pl_pattern_recorded, LeftButtonState.Redraw, RightButtonState.Continue,
                false),
        Confirm(R.string.pl_confirm_pattern, LeftButtonState.Cancel,
                RightButtonState.ConfirmDisabled, true),
        ConfirmWrong(R.string.pl_wrong_pattern, LeftButtonState.Cancel,
                RightButtonState.ConfirmDisabled, true),
        ConfirmCorrect(R.string.pl_pattern_confirmed, LeftButtonState.Cancel,
                RightButtonState.Confirm, false),
        ConfirmUpdate(R.string.modify_success, LeftButtonState.Cancel,
                RightButtonState.Confirm, false);

        public final int messageId;
        public final LeftButtonState leftButtonState;

        public final RightButtonState rightButtonState;

        public final boolean patternEnabled;

        Stage(int messageId, LeftButtonState leftButtonState, RightButtonState rightButtonState,
              boolean patternEnabled) {
            this.messageId = messageId;
            this.leftButtonState = leftButtonState;
            this.rightButtonState = rightButtonState;
            this.patternEnabled = patternEnabled;
        }
    }
}
